/* 
 * Copyright 2011 kOSMik.
 * This file is part of kOSMik.
 * 
 * kOSMik is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * kOSMik is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with kOSMik.  If not, see <http://www.gnu.org/licenses/>.
 *  
 * kOSMik:
 * Open Street Map - Editor.
 * http://code.google.com/p/swp-dv-ws2010-osm-2/
 */

package de.fuberlin.kosmik.data.osmt;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.util.Log;
import de.fuberlin.kosmik.log.Constants;

/**
 * This class should be changed or depreciated.
 */
class OsmtDatabaseImpl implements OsmtDatabase {

	private final OsmtOpenHelper databaseOpenHelper;
	private final SQLiteDatabase readableDatabase;
	private final SQLiteDatabase writableDatabase;

	/**
	 * Constructor.
	 * 
	 * @param context that wants access to the database
	 */
	public OsmtDatabaseImpl(Context context) {
		databaseOpenHelper = new OsmtOpenHelper(context);
		readableDatabase = databaseOpenHelper.getReadableDatabase();
		writableDatabase = databaseOpenHelper.getWritableDatabase();
	}

	/**
	 * Returns a readable SQLiteDatabase object.
	 * 
	 * @return a readable database
	 */
	SQLiteDatabase getReadableDatabase() {
		return readableDatabase;
	}

	/**
	 * Inserts a record into the database.
	 * 
	 * @param osmtTable the target table into which the row should be written.
	 * @param values are forming the record that should be written.
	 * @return true, if the record was written, and false, if the was not
	 *         written. A cause is for e.g. that a SQLiteContraintsException
	 *         occur.
	 */
	@Override
	public boolean insertRecord(OsmtTable osmtTable, ContentValues values) {
		try {
			writableDatabase.beginTransaction();
			long rowId = writableDatabase.insert(osmtTable.getTableName(), null, values);
			if (rowId == -1) {
				Log.d(Constants.TAG,
						String.format("error while insert row in table %s.",
								osmtTable.getTableName()));
				return false;
			}

			// Log.d(Constants.TAG,
			// String.format("inserted a row at index %d in table %s successfully.",
			// Long.valueOf(rowId), osmtTable.getTableName()));
			writableDatabase.setTransactionSuccessful();
			return true;
		} catch (SQLiteException e) {
			return false;
		} finally {
			writableDatabase.endTransaction();
		}
	}

	/**
	 * Updates an record that already exists.
	 * 
	 * @param osmtTable identifies the table on which the update is performed.
	 * @param values which replaces the old ones
	 * @param whereClause specifies the condition under which the update is to
	 *            take place.
	 * @param whereArgs are arguments that inserts in the whereClause.
	 *            whereClause and whereArgs are optional. Passing null will
	 *            update all rows.
	 * @return true, if update happen, otherwise false
	 */
	@Override
	public boolean update(OsmtTable osmtTable, ContentValues values, String whereClause,
			String[] whereArgs) {
		try {
			writableDatabase.beginTransaction();
			writableDatabase.update(osmtTable.getTableName(), values, whereClause, whereArgs);
			writableDatabase.setTransactionSuccessful();
			return true;
		} catch (SQLiteException e) {
			return false;
		} finally {
			writableDatabase.endTransaction();
		}
	}

	/**
	 * Handles a query. Forward the query encapsulated in the OsmtQuery-object
	 * and return the gained cursor to the callback-method.
	 * 
	 * @param query The encapsulated query that forwarded to the database
	 * @param onObtainCursorListener that implements the onObtainCursor-method
	 *            to process the query results
	 * @return the result that returned by onObtainCursor
	 */
	@Override
	public boolean query(OsmtQuery query, OnObtainCursorListener onObtainCursorListener) {
		Cursor cursor = null;
		try {
			Log.d(Constants.TAG, String.format("do query on table %s.", query.getTable()));
			cursor = query.executeOnDatabase(readableDatabase);
			if (onObtainCursorListener.onObtainCursor(cursor)) {
				// it is important to close the cursor finally!!!
				// Log.d(Constants.TAG,
				// String.format("query on table %s processed successfully.",
				// query.getTable()));
				return true;
			}
			Log.d(Constants.TAG,
					String.format("query on table %s didn't processed.", query.getTable()));
			return false;
		} catch (SQLiteException e) {
			return false;
		} finally {
			// it is important to close the cursor finally!!!
			if (cursor != null) {
				cursor.close();
			}
		}
	}

	/**
	 * Handles a raw query. Return the gained cursor to the callback-method.
	 * 
	 * @param query The raw query string.
	 * @param onObtainCursorListener that implements the onObtainCursor-method
	 *            to process the query results
	 * @return the result that returned by onObtainCursor
	 */
	@Override
	public boolean query(String query, OnObtainCursorListener onObtainCursorListener) {
		Cursor cursor = null;
		try {
			readableDatabase.beginTransaction();
			Log.d(Constants.TAG, String.format("do raw query %s.", query));
			cursor = readableDatabase.rawQuery(query, null);
			if (onObtainCursorListener.onObtainCursor(cursor)) {
				// it is important to close the cursor finally!!!
				// Log.d(Constants.TAG, "raw query processed successfully.");
				readableDatabase.setTransactionSuccessful();
				return true;
			}
			Log.w(Constants.TAG, "raw query didn't processed.");
			return false;
		} catch (SQLiteException e) {
			Log.e(Constants.TAG, "ERROR: " + e.getMessage());
			return false;
		} finally {
			// it is important to close the cursor finally!!!
			if (cursor != null) {
				cursor.close();
			}
			readableDatabase.endTransaction();
		}
	}

	// public void fetchAllValues(Collection<String> collection) {
	// Cursor cursor = readableDatabase.query(OsmtValue.TABLE, null, null, null,
	// null, null,
	// null);
	// cursor.moveToFirst();
	// Log.d(Constants.TAG,
	// String.format("table values contains  %d rows ", cursor.getCount()));
	//
	// }

	@Override
	public boolean delete(OsmtTable osmtTable, String whereClause, String[] whereArgs) {
		try {
			writableDatabase.beginTransaction();
			writableDatabase.delete(osmtTable.getTableName(), whereClause, whereArgs);
			writableDatabase.endTransaction();
			return false;
		} catch (SQLiteException e) {
			return false;
		} finally {
			writableDatabase.endTransaction();
		}
	}

}
